package com.stars.easyms.demo.restservice.sentinel;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.stars.easyms.demo.dto.input.sentinel.SentinelDemo1Input;
import com.stars.easyms.demo.dto.output.sentinel.SentinelDemo1Output;
import com.stars.easyms.rest.RestService;
import com.stars.easyms.base.util.MessageFormatUtil;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * sentinel手动注入流控规则
 *
 * @author guoguifang
 * @date 2018-04-23 13:54
 * @since 1.0.0
 */
@Service
public class SentinelDemo1Service implements RestService<SentinelDemo1Input, SentinelDemo1Output> {

    private static final String RESOURCE_NAME = SentinelDemo1Service.class.getSimpleName();

    @Override
    public SentinelDemo1Output execute(SentinelDemo1Input input) {
        defineFlowRules(input);
        int successCount = 0, blockCount = 0;
        // 单线程循环，无法测试线程类型的限流
        for (int i = 0; i < input.getTimes(); i++) {
            // 循环times次，如果阈值达到则限流抛出BlockException
            try (Entry entry = SphU.entry(RESOURCE_NAME)) {
                System.out.println(RESOURCE_NAME);
                successCount++;
            } catch (BlockException e1) {
                blockCount++;
            }
        }
        SentinelDemo1Output output = new SentinelDemo1Output();
        System.out.println(MessageFormatUtil.format("Rest Service[{}], param[{}]!", this.getClass().getSimpleName(), input));
        output.setSuccessCount(successCount);
        output.setBlockCount(blockCount);
        return null;
    }

    private void defineFlowRules(SentinelDemo1Input input) {
        List<FlowRule> rules = new ArrayList<>();
        // 定义该规则为流控规则
        FlowRule rule = new FlowRule();
        // 定义资源名称
        rule.setResource(RESOURCE_NAME);
        // 定义流控阈值类型(0: threadCount, 1: QPS)
        rule.setGrade(input.getGrade());
        // 定义单机阈值.
        rule.setCount(input.getCount());
        // 定义流控模式(0: 直接(默认), 1: 关联, 2: 链路)
        rule.setStrategy(input.getStrategy());
        // 定义流控效果(0: 快速失败, 1: 预热, 2: 排队等待, 3: 预热 + 排队等待)
        rule.setControlBehavior(input.getControlBehavior());
        // 定义预热时长,默认10,单位:秒(流控效果为2或3时有效)
        rule.setWarmUpPeriodSec(input.getWarmUpPeriodSec());
        // 定义最大排队等待时间,默认500,单位:毫秒(流控效果为2或3时有效)
        rule.setMaxQueueingTimeMs(input.getMaxQueueingTimeMs());
        rules.add(rule);
        FlowRuleManager.loadRules(rules);
    }

}


